home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / WindowMaker / WINGs / wscrollview.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-10-09  |  10.0 KB  |  505 lines

  1.  
  2.  
  3.  
  4.  
  5. #include "WINGsP.h"
  6.  
  7.  
  8. typedef struct W_ScrollView {
  9.     W_Class widgetClass;
  10.     WMView *view;
  11.  
  12.     WMView *contentView;
  13.     WMView *viewport;
  14.     
  15.     WMScroller *vScroller;
  16.     WMScroller *hScroller;
  17.     
  18.     short lineScroll;
  19.     short pageScroll;
  20.     
  21.     struct {
  22.     WMReliefType relief:3;
  23.     unsigned int hasVScroller:1;
  24.     unsigned int hasHScroller:1;
  25.     
  26.     } flags;
  27.     
  28. } ScrollView;
  29.  
  30.  
  31.  
  32.  
  33. static void destroyScrollView(ScrollView *sPtr);
  34.  
  35. static void paintScrollView(ScrollView *sPtr);
  36. static void handleEvents(XEvent *event, void *data);
  37. static void handleViewportEvents(XEvent *event, void *data);
  38. static void resizeScrollView();
  39.  
  40.  
  41. W_ViewDelegate _ScrollViewViewDelegate = {
  42.     NULL,
  43.     NULL,
  44.     resizeScrollView,
  45.     NULL,
  46.     NULL
  47. };
  48.  
  49.  
  50.           
  51. WMScrollView*
  52. WMCreateScrollView(WMWidget *parent)
  53. {
  54.     ScrollView *sPtr;
  55.  
  56.     sPtr = wmalloc(sizeof(ScrollView));
  57.     memset(sPtr, 0, sizeof(ScrollView));
  58.  
  59.     sPtr->widgetClass = WC_ScrollView;
  60.     
  61.     sPtr->view = W_CreateView(W_VIEW(parent));
  62.     if (!sPtr->view) {
  63.     wfree(sPtr);
  64.     return NULL;
  65.     }
  66.     sPtr->viewport = W_CreateView(sPtr->view);
  67.     if (!sPtr->view) {
  68.     W_DestroyView(sPtr->view);
  69.     wfree(sPtr);
  70.     return NULL;
  71.     }
  72.     sPtr->view->self = sPtr;
  73.  
  74.     sPtr->view->delegate = &_ScrollViewViewDelegate;
  75.  
  76.     sPtr->viewport->flags.mapWhenRealized = 1;
  77.  
  78.     WMCreateEventHandler(sPtr->view, StructureNotifyMask|ExposureMask,
  79.              handleEvents, sPtr);
  80.     WMCreateEventHandler(sPtr->viewport, SubstructureNotifyMask, 
  81.              handleViewportEvents, sPtr);
  82.  
  83.     sPtr->lineScroll = 4;
  84.  
  85.     sPtr->pageScroll = 0;
  86.  
  87.     return sPtr;
  88. }
  89.  
  90.  
  91.  
  92. static void
  93. reorganizeInterior(WMScrollView *sPtr)
  94. {
  95.     int hx, hy, hw;
  96.     int vx, vy, vh;
  97.     int cx, cy, cw, ch;
  98.     
  99.     
  100.     cw = hw = sPtr->view->size.width;
  101.     vh = ch = sPtr->view->size.height;
  102.  
  103.     if (sPtr->flags.relief == WRSimple) {
  104.     cw -= 2;
  105.     ch -= 2;
  106.     cx = 1;
  107.     cy = 1;    
  108.     } else if (sPtr->flags.relief != WRFlat) {
  109.     cw -= 3;
  110.     ch -= 3;
  111.     cx = 2;
  112.     cy = 2;
  113.     } else {
  114.     cx = 0;
  115.     cy = 0;
  116.     }
  117.     
  118.     if (sPtr->flags.hasHScroller) {
  119.     int h = W_VIEW(sPtr->hScroller)->size.height;
  120.  
  121.     ch -= h;
  122.  
  123.     if (sPtr->flags.relief == WRSimple) {
  124.         hx = 0;
  125.         hy = sPtr->view->size.height - h;
  126.     } else if (sPtr->flags.relief != WRFlat) {
  127.         hx = 1;
  128.         hy = sPtr->view->size.height - h - 1;
  129.         hw -= 2;
  130.     } else {
  131.         hx = 0;
  132.         hy = sPtr->view->size.height - h;
  133.     }
  134.     } else {
  135.     /* make compiler shutup */
  136.     hx = 0;
  137.     hy = 0;
  138.     }
  139.     
  140.     if (sPtr->flags.hasVScroller) {
  141.     int w = W_VIEW(sPtr->vScroller)->size.width;
  142.     cw -= w;
  143.     cx += w;
  144.     hx += w - 1;
  145.     hw -= w - 1;
  146.  
  147.     if (sPtr->flags.relief == WRSimple) {
  148.         vx = 0;
  149.         vy = 0;
  150.     } else if (sPtr->flags.relief != WRFlat) {
  151.         vx = 1;
  152.         vy = 1;
  153.         vh -= 2;
  154.     } else {
  155.         vx = 0;
  156.         vy = 0;
  157.     }
  158.     } else {
  159.     /* make compiler shutup */
  160.     vx = 0;
  161.     vy = 0;
  162.     }
  163.  
  164.     W_ResizeView(sPtr->viewport, cw, ch);
  165.     W_MoveView(sPtr->viewport, cx, cy);
  166.     
  167.     if (sPtr->flags.hasHScroller) {
  168.     WMResizeWidget(sPtr->hScroller, hw, 20);
  169.     WMMoveWidget(sPtr->hScroller, hx, hy);
  170.     }
  171.     if (sPtr->flags.hasVScroller) {
  172.     WMResizeWidget(sPtr->vScroller, 20, vh);
  173.     WMMoveWidget(sPtr->vScroller, vx, vy);
  174.     }
  175. }
  176.  
  177.  
  178. static void
  179. resizeScrollView(W_ViewDelegate *self, WMView *view)
  180. {
  181.     reorganizeInterior(view->self);
  182. }
  183.  
  184.  
  185.  
  186. void
  187. WMResizeScrollViewContent(WMScrollView *sPtr, unsigned int width, 
  188.               unsigned int height)
  189. {
  190.     int w, h, x;
  191.  
  192.     w = width;
  193.     h = height;
  194.  
  195.     x = 0;
  196.     if (sPtr->flags.relief == WRSimple) {
  197.     w += 2;
  198.     h += 2;
  199.     } else if (sPtr->flags.relief != WRFlat) {
  200.     w += 4;
  201.     h += 4;
  202.     x = 1;
  203.     }
  204.     
  205.     if (sPtr->flags.hasVScroller) {
  206.     w -= W_VIEW(sPtr->hScroller)->size.width;
  207.     WMResizeWidget(sPtr->vScroller, 20, h);
  208.     }    
  209.     if (sPtr->flags.hasHScroller) {
  210.     h -= W_VIEW(sPtr->hScroller)->size.height;
  211.     WMResizeWidget(sPtr->hScroller, w, 20);
  212.     WMMoveWidget(sPtr->hScroller, x, h);
  213.     }
  214.  
  215.     W_ResizeView(sPtr->view, w, h);
  216.  
  217.     W_ResizeView(sPtr->viewport, width, height);
  218. }
  219.  
  220.  
  221. void
  222. WMSetScrollViewLineScroll(WMScrollView *sPtr, int amount)
  223. {
  224.     assert(amount > 0);
  225.     
  226.     sPtr->lineScroll = amount;
  227. }
  228.  
  229.  
  230. void
  231. WMSetScrollViewPageScroll(WMScrollView *sPtr, int amount)
  232. {
  233.     assert(amount >= 0);
  234.  
  235.     sPtr->pageScroll = amount;
  236. }
  237.  
  238.  
  239. static void
  240. doScrolling(WMWidget *self, void *data)
  241. {
  242.     ScrollView *sPtr = (ScrollView*)data;
  243.     float value;
  244.     int pos;
  245.     int vpsize;
  246.     float size;
  247.     
  248.     if (sPtr->hScroller == (WMScroller *)self) {
  249.     pos = -sPtr->contentView->pos.x;
  250.     size = sPtr->contentView->size.width-sPtr->viewport->size.width;
  251.     vpsize = sPtr->viewport->size.width - sPtr->pageScroll;
  252.     } else {
  253.     pos = -sPtr->contentView->pos.y;
  254.     size = sPtr->contentView->size.height-sPtr->viewport->size.height;
  255.     vpsize = sPtr->viewport->size.height - sPtr->pageScroll;
  256.     }
  257.     if (vpsize <= 0)
  258.     vpsize = 1;
  259.  
  260.     switch (WMGetScrollerHitPart(self)) {
  261.      case WSDecrementLine:
  262.     if (pos > 0) {
  263.         pos-=sPtr->lineScroll;
  264.         if (pos < 0)
  265.         pos = 0;
  266.         value = (float)pos / size;
  267.         WMSetScrollerParameters(self, value,
  268.                     WMGetScrollerKnobProportion(self));
  269.     }
  270.     break;
  271.      case WSIncrementLine:
  272.     if (pos < size) {
  273.         pos+=sPtr->lineScroll;
  274.         if (pos > size)
  275.         pos = size;
  276.         value = (float)pos / size;
  277.         WMSetScrollerParameters(self, value,
  278.                     WMGetScrollerKnobProportion(self));
  279.     }
  280.     break;
  281.      case WSKnob:
  282.     value = WMGetScrollerValue(self);
  283.     pos = value*size;
  284.     break;
  285.     
  286.      case WSDecrementPage:
  287.     if (pos > 0) {
  288.         pos -= vpsize;
  289.         if (pos < 0)
  290.         pos = 0;
  291.         value = (float)pos / size;
  292.         WMSetScrollerParameters(self, value,
  293.                     WMGetScrollerKnobProportion(self));
  294.     }
  295.     break;
  296.     
  297.      case WSIncrementPage:
  298.     if (pos < size) {
  299.         pos += vpsize;
  300.         if (pos > size)
  301.         pos = size;
  302.         value = (float)pos / size;
  303.         WMSetScrollerParameters(self, value,
  304.                     WMGetScrollerKnobProportion(self));
  305.     }
  306.     break;
  307.     
  308.      case WSNoPart:
  309.      case WSKnobSlot:
  310.     break;
  311.     }
  312.     
  313.     if (sPtr->hScroller == (WMScroller *)self) {
  314.     W_MoveView(sPtr->contentView, -pos, sPtr->contentView->pos.y);
  315.     } else {
  316.     W_MoveView(sPtr->contentView, sPtr->contentView->pos.x, -pos);
  317.     }
  318. }
  319.  
  320.  
  321. WMScroller*
  322. WMGetScrollViewHorizontalScroller(WMScrollView *sPtr)
  323. {
  324.     return sPtr->hScroller;
  325. }
  326.  
  327.  
  328.  
  329. WMScroller*
  330. WMGetScrollViewVerticalScroller(WMScrollView *sPtr)
  331. {
  332.     return sPtr->vScroller;
  333. }
  334.  
  335.  
  336. void
  337. WMSetScrollViewHasHorizontalScroller(WMScrollView *sPtr, Bool flag)
  338. {
  339.     if (flag) {
  340.     if (sPtr->flags.hasHScroller)
  341.         return;
  342.     sPtr->flags.hasHScroller = 1;
  343.     
  344.     sPtr->hScroller = WMCreateScroller(sPtr);
  345.     WMSetScrollerAction(sPtr->hScroller, doScrolling, sPtr);
  346.     /* make it a horiz. scroller */
  347.     WMResizeWidget(sPtr->hScroller, 2, 1);
  348.  
  349.     reorganizeInterior(sPtr);
  350.  
  351.     WMMapWidget(sPtr->hScroller);
  352.     } else {
  353.     if (!sPtr->flags.hasHScroller)
  354.         return;
  355.     
  356.     WMUnmapWidget(sPtr->hScroller);
  357.     WMDestroyWidget(sPtr->hScroller);
  358.     sPtr->hScroller = NULL;
  359.     sPtr->flags.hasHScroller = 0;
  360.     
  361.     reorganizeInterior(sPtr);
  362.     }
  363. }
  364.  
  365.  
  366. void
  367. WMSetScrollViewHasVerticalScroller(WMScrollView *sPtr, Bool flag)
  368. {
  369.     if (flag) {
  370.     if (sPtr->flags.hasVScroller)
  371.         return;
  372.     sPtr->flags.hasVScroller = 1;
  373.     
  374.     sPtr->vScroller = WMCreateScroller(sPtr);
  375.     WMSetScrollerAction(sPtr->vScroller, doScrolling, sPtr);
  376.     WMSetScrollerArrowsPosition(sPtr->vScroller, WSAMaxEnd);
  377.     /* make it a vert. scroller */
  378.     WMResizeWidget(sPtr->vScroller, 1, 2);
  379.  
  380.     reorganizeInterior(sPtr);
  381.     
  382.     WMMapWidget(sPtr->vScroller);
  383.     } else {
  384.     if (!sPtr->flags.hasVScroller)
  385.         return;
  386.     sPtr->flags.hasVScroller = 0;
  387.     
  388.     WMUnmapWidget(sPtr->vScroller);
  389.     WMDestroyWidget(sPtr->vScroller);
  390.     sPtr->vScroller = NULL;
  391.  
  392.     reorganizeInterior(sPtr);
  393.     }
  394. }
  395.  
  396.  
  397. void
  398. WMSetScrollViewContentView(WMScrollView *sPtr, WMView *view)
  399. {
  400.     assert(sPtr->contentView == NULL);
  401.     
  402.     sPtr->contentView = view;
  403.  
  404.     W_ReparentView(sPtr->contentView, sPtr->viewport, 0, 0);
  405.  
  406.     if (sPtr->flags.hasHScroller) {
  407.     float prop;
  408.     
  409.     prop = (float)sPtr->viewport->size.width/sPtr->contentView->size.width;
  410.     WMSetScrollerParameters(sPtr->hScroller, 0, prop);
  411.     }
  412.     if (sPtr->flags.hasVScroller) {
  413.     float prop;
  414.     
  415.     prop = (float)sPtr->viewport->size.height/sPtr->contentView->size.height;
  416.     
  417.     WMSetScrollerParameters(sPtr->vScroller, 0, prop);
  418.     }
  419. }
  420.  
  421.  
  422. void
  423. WMSetScrollViewRelief(WMScrollView *sPtr, WMReliefType type)
  424. {
  425.     sPtr->flags.relief = type;
  426.     
  427.     if (sPtr->view->flags.mapped)
  428.     paintScrollView(sPtr);
  429.     
  430.     
  431. }
  432.  
  433.  
  434. static void
  435. paintScrollView(ScrollView *sPtr)
  436. {
  437.     W_DrawRelief(sPtr->view->screen, sPtr->view->window, 0, 0,
  438.          sPtr->view->size.width, sPtr->view->size.height,
  439.          sPtr->flags.relief);
  440. }
  441.  
  442.  
  443. static void
  444. updateScrollerProportion(ScrollView *sPtr)
  445. {
  446.     float prop, value;
  447.     
  448.     if (sPtr->flags.hasHScroller) {
  449.     prop = (float)sPtr->viewport->size.width/sPtr->contentView->size.width;
  450.     value = WMGetScrollerValue(sPtr->hScroller);
  451.     
  452.     WMSetScrollerParameters(sPtr->hScroller, value, prop);
  453.     }
  454.     if (sPtr->flags.hasVScroller) {
  455.     prop = (float)sPtr->viewport->size.height/sPtr->contentView->size.height;
  456.     
  457.     value = WMGetScrollerValue(sPtr->vScroller);
  458.     
  459.     WMSetScrollerParameters(sPtr->vScroller, value, prop);
  460.     }
  461. }
  462.  
  463.  
  464. static void
  465. handleViewportEvents(XEvent *event, void *data)
  466. {
  467.     ScrollView *sPtr = (ScrollView*)data;
  468.  
  469.     if (sPtr->contentView 
  470.     && event->xconfigure.window == sPtr->contentView->window)
  471.     updateScrollerProportion(sPtr);
  472. }
  473.  
  474.  
  475. static void
  476. handleEvents(XEvent *event, void *data)
  477. {
  478.     ScrollView *sPtr = (ScrollView*)data;
  479.  
  480.     CHECK_CLASS(data, WC_ScrollView);
  481.  
  482.     switch (event->type) {    
  483.      case Expose:
  484.     if (event->xexpose.count!=0)
  485.         break;
  486.     paintScrollView(sPtr);
  487.     break;
  488.     
  489.      case DestroyNotify:
  490.     destroyScrollView(sPtr);
  491.     break;
  492.     
  493.     }
  494. }
  495.  
  496.  
  497. static void
  498. destroyScrollView(ScrollView *sPtr)
  499. {
  500.     
  501.    
  502.     wfree(sPtr);
  503. }
  504.  
  505.